import json
import os
import time
from typing import Dict, Any

import pymysql
import requests

from logger import log
from settings import settings

# --- 配置区 ---
CONFIG_FILE = 'last.json'

# 请根据您的实际情况修改
DB_CONFIG = {
    'host': '192.168.10.140',
    'port': 3306,
    'user': 'root',
    'password': 'galaxy123',
    'db': 'loaddetect',
    'charset': 'utf8mb4',
    'cursorclass': pymysql.cursors.DictCursor  # 使用字典游标
}


def upload_image(file_path, tenant_id, model_code, field_code, file_name="img.png"):
    retries = 3
    for i in range(retries):
        try:
            with open(settings.directory + file_path, 'rb') as file:
                # 创建表单数据
                files = {'contractFile': (file_name, file)}
                params = {
                    'accessCode': 'oss',
                    'tenantId': tenant_id,
                    'modelCode': model_code,
                    'fieldCode': field_code
                }
                # 设置请求的URL
                url = f'http://platform.wechain360.com/api/account/oss/fileUpload'
                # 发送POST请求
                response = requests.post(url, files=files, params=params, verify=False, timeout=10)
                response.raise_for_status()  # 如果请求返回了错误状态码，这会抛出异常
                # 处理响应
                log.info(f"图片上传数据返回:{response.json()}")
                snapshotUrl = response.json()['data']
                return snapshotUrl
        except Exception as e:
            log.warn(f"upload_image attempt {i + 1} of {retries} failed with error: {e}")
            if i < retries - 1:  # if not the last attempt
                time.sleep(1)  # wait for 1 second
    log.error("upload_image failed after all retries.")
    return None


def load_config() -> Dict[str, Any]:
    """加载配置文件"""
    if not os.path.exists(CONFIG_FILE):
        default_config = {
            'last_processed_id': 0,
            'result_time': None
        }
        with open(CONFIG_FILE, 'w') as f:
            json.dump(default_config, f, indent=4)
        return default_config

    with open(CONFIG_FILE, 'r') as f:
        return json.load(f)


def save_config(config: Dict[str, Any]) -> None:
    """保存配置文件"""
    with open(CONFIG_FILE, 'w') as f:
        json.dump(config, f, indent=4)


def fetch_new_records(last_processed_id: int) -> list:
    """获取未处理的新记录（使用字典游标）"""
    connection = pymysql.connect(**DB_CONFIG)
    try:
        with connection.cursor() as cursor:
            sql = """
            select 
                r.*,
                t.BaseHeight-r.TrainFullUpHeight as load_height,
                t.BaseVol - r.TrainFullLoadVol as load_vol
            from tab_result r join tab_traintype t on r.TrainTypeName = t.TrainTypeName
            WHERE r.ResultId > %s 
            ORDER BY r.ResultId ASC
            """
            cursor.execute(sql, (last_processed_id,))
            return cursor.fetchall()
    finally:
        connection.close()


def convert_to_train_node(db_record: Dict[str, Any]) -> Dict[str, Any]:
    """将数据库记录转换为TrainNodeCO对象（使用字段名访问）"""
    record = {
        'platformId': settings.platformId,
        'platformName': settings.platformName,

        'controller_no': db_record.get('ControllerNo'),

        'train_type': db_record.get('TrainTypeName'),
        'train_no': db_record.get('TrainNo'),
        'reach_time': db_record.get('ResultTime').strftime('%Y-%m-%d %H:%M:%S') if db_record.get(
            'ResultTime') else None,
        'empty_or_full': db_record.get('OutOrIn'),
        'alarm_bar': db_record.get('TrainEmptyBarAlarm'),
        'alarm_matter': db_record.get('TrainEmptyBottomAlarm'),
        'alarm_side': db_record.get('TrainEmptySiderAlarm'),
        'alarm_frozen': db_record.get('TrainEmptyFrozenAlarm'),
        'alarm_unbalance': db_record.get('TrainFullDivAlarm'),
        'alarm_unbalance_vol1': db_record.get('TrainFullDivLeftRightVol'),
        'alarm_unbalance_vol2': db_record.get('TrainFullDivForBackVol'),
        'load_height': db_record.get('load_height'),
        'up_height': db_record.get('TrainFullUpHeight'),
        'load_vol': db_record.get('load_vol'),
        'pic_file1': upload_image(f"Pic/{db_record.get('TrainPic1')}", 1648, "carriage_jz", "pic_file1"),
        'pic_file2': upload_image(f"Pic/{db_record.get('TrainPic2')}", 1648, "carriage_jz", "pic_file2"),
        'point_file': upload_image(f"Point/{db_record.get('Train3D')}", 1648, "carriage_jz", "point_file", 'dy.dy'),
    }
    return record


def send_to_api(data: Dict[str, Any]) -> bool:
    """发送数据到API"""
    headers = {'Content-Type': 'application/json'}
    try:
        url = settings.server_url + "/depatch/internal/train/trainCpz"
        response = requests.post(url, data=json.dumps(data), headers=headers)
        if response.status_code == 200:
            response_json = response.json()
            if response_json.get('code') == '0000':
                log.info(f"成功发送记录: {data.get('code')}")
                return True
        log.warn(f"发送失败: {response.status_code}, {response.text}")
        return False
    except Exception as e:
        log.warn(f"API请求异常: {str(e)}")
        return False


def process_record(record: Dict[str, Any], config: Dict[str, Any]) -> bool:
    """处理单条记录"""
    if record.get('TrainSerial') == 1:
        # 请求更新上一个列告警次数
        config['result_time'] = record.get('ResultTime').strftime('%Y-%m-%d %H:%M:%S')
    train_node = convert_to_train_node(record)
    # 设置trainCode，新的会创建新的列
    train_node['begin_time'] = config['result_time']

    # 发送到相应接口
    success = send_to_api(train_node)

    if success:
        # 更新最后处理的ID
        config['last_processed_id'] = record.get('ResultId')
        # 保存配置
        save_config(config)
        log.info("配置已更新")

        return True
    return False


def collection():
    # 加载配置
    config = load_config()
    log.info(f"当前配置: 最后处理ID={config['last_processed_id']}")

    # 获取新记录
    records = fetch_new_records(config['last_processed_id'])
    if not records:
        log.info("没有需要处理的新记录")
        return

    log.info(f"找到 {len(records)} 条新记录")

    # 处理每条记录
    for record in records:
        if process_record(record, config):
            log.info(f"记录 {record.get('ResultId')} 处理完成")
        else:
            log.warn(f"记录 {record.get('ResultId')} 处理失败，停止处理后续记录")
            break


def main():
    """主函数"""
    log.info("开始运行")
    while True:
        try:
            collection()
        except Exception as e:
            log.error(f"collection异常: {str(e)}", e)
        time.sleep(300)


if __name__ == '__main__':
    settings.init(local=True)
    main()
